package com.stars.easyms.security.jwt;

import com.stars.easyms.security.constant.EasyMsSecurityConstants;
import com.stars.easyms.security.matcher.EasyMsRequestMatcher;
import com.stars.easyms.security.properties.EasyMsSecurityProperties;
import org.springframework.web.filter.GenericFilterBean;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * JWT过滤类：过滤传入的请求，如果找到与有效用户对应的头，则安装Spring安全主体。
 *
 * @author guoguifang
 * @date 2020-08-12 17:24
 * @since 1.6.0
 */
public class EasyMsJWTFilter extends GenericFilterBean {

    private final EasyMsSecurityProperties easyMsSecurityProperties;

    private final EasyMsJWTProvider easyMsJWTProvider;

    private final EasyMsRequestMatcher easyMsRequestMatcher;

    EasyMsJWTFilter(EasyMsSecurityProperties easyMsSecurityProperties, EasyMsJWTProvider easyMsJWTProvider) {
        this.easyMsSecurityProperties = easyMsSecurityProperties;
        this.easyMsJWTProvider = easyMsJWTProvider;
        this.easyMsRequestMatcher = new EasyMsRequestMatcher();
        this.init();
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
        throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;

        // 不做jwt验证的直接跳过检查
        if (easyMsRequestMatcher.matches(httpServletRequest)) {
            filterChain.doFilter(servletRequest, servletResponse);
        } else {
            // 先从header头获取jwt，然后检查若检查通过则将转换后的存放到本地线程变量中，若检查不通过直接返回没有权限
            String jwt = resolveToken(httpServletRequest);
            if (StringUtils.hasText(jwt)) {
                UserInfo userInfo = this.easyMsJWTProvider.getAuthentication(jwt);
                if (userInfo == null) {
                    System.out.println("校验失败");
                } else {
                    System.out.println(userInfo);
                    filterChain.doFilter(servletRequest, servletResponse);
                }
            } else {
                System.out.println("校验失败");
            }
        }
    }

    private void init() {
        // 获取不需要做jwt验证的url的requestMatcher
        EasyMsSecurityConstants.EASY_MS_URL.forEach(easyMsRequestMatcher::antMatchers);
        if (!StringUtils.isEmpty(easyMsSecurityProperties.getJwt().getPermit())) {
            for (String str : StringUtils.tokenizeToStringArray(easyMsSecurityProperties.getJwt().getPermit(),
                    EasyMsSecurityConstants.PROPERTIES_SEPARATOR)) {
                easyMsRequestMatcher.antMatchers(str);
            }
        }
    }

    private String resolveToken(HttpServletRequest request) {
        String bearerToken = request.getHeader(easyMsSecurityProperties.getJwt().getHeaderKey());
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(EasyMsSecurityConstants.HEADER_TOKEN_PREFIX)) {
            return bearerToken.substring(EasyMsSecurityConstants.HEADER_TOKEN_PREFIX.length());
        }
        return null;
    }
}
